[アップデート] AWS Amplify for JavaScript がS3のリジューム可能なファイルアップロードをサポートしました
こんにちは、リサリサです。
AWS Amplify for JavaScript がストレージのリジューム可能なファイルアップロードをサポートしたので触ってみました。
※フロント全然分からない人間が書いています。vue.js 今回初めて触りました…。なので、ソースコード等、細かい部分はあまり当てにしないで頂けると幸いです。あくまでアップデートした機能の動きの参考と見て頂ければと思います。
追加された事
AWS Amplify for JavaScript がストレージのリジューム可能なファイルアップロードをサポート
AWS Amplify for JavaScript は、Amplify ストレージカテゴリ経由で Simple Storage Service(Amazon S3) にファイルをアップロードする際の一時停止、再開、キャンセルのアクションに対応しました。Amplify はユースケース指向の UI コンポーネント、ライブラリ、コマンドラインツールのセットを提供し、フロントエンドのウェブやモバイルのデベロッパーがアプリケーションのための AWS クラウドバックエンドを簡単に構築できるようにします。
S3 アップロードの一時停止、再開、キャンセルが出来るようになったようです。また、途中で通信が途切れた場合なども、途中から再開が出来るようです。
const upload = Storage.put(file.name, file, { resumable: true, }); //一時停止 upload.pause(); //再開 upload.resume(); //キャンセル Storage.cancel(upload);
やってみた
S3 にアップロードできるアプリを作る
以下ブログを元にS3にアップロードができるアプリケーションをまず作ってみます。
基本的にはブログ通りに進めるのですが、少し古い記事で、サンプルソースもあまり更新がされておらずライブラリが古めです。サンプルソースのままだと amplify のバージョンが古くて今回追加されたメソッドが使えません。なので、試される方は git からcloneした後、package.json の dependencies を以下に書き換えてから「yarn install」してみてください。
"dependencies": { "@vue/cli-plugin-unit-jest": "^3.2.0", "@vue/cli-service": "^3.2.0", "@vue/test-utils": "^1.0.0-beta.27", "aws-amplify": "^4.3.4", "aws-amplify-vue": "^2.1.5", "aws-sdk": "^2.1022.0", "e": "0.0.4", "element-ui": "^2.15.6", "fsts": "^0.0.39", "vue": "^2.5.16", "vue-router": "^3.0.1", "vuex": "^3.0.1" },
ブログ通りに進め、ユーザー作成までするとこのような画面になります。
S3 アップロード、ダウンロード、削除ができるアプリが完成です。
一時停止、再開、キャンセルの機能を追加
ここに、一時停止、再開、キャンセルの機能を追加して、動作確認してみます。
src/Home.vue
を以下のように変更します。
pause、resume、cancel、というボタンを追加して、それぞれのメソッドを追加しています。また、「progressCallback」で、どこまで送信したかを監視していきます。
<template> <div class="container shifted"> <h1 class="h1"> S3 Objects </h1> <el-button> <label for="file"> Upload <input type="file" @change="upload" id="file" style="display:none;"> </label> </el-button> <el-button @click="pause">pause</el-button> <el-button @click="resume">resume</el-button> <el-button @click="cancel">cancel</el-button> <el-button @click="refresh" class="el-icon-refresh-left"></el-button> <el-table :data="s3Data" style="width: 100%"> <el-table-column prop="key" label="Key" sortable> </el-table-column> <el-table-column prop='lastModified' label="LastModified" sortable> </el-table-column> <el-table-column prop="size" label="Size" sortable> </el-table-column> <el-table-column> <template slot-scope="scope"> <el-button @click="download(scope.row)">Download</el-button> <el-button type="danger" @click="openDeleteDialog(scope.row)">Delete</el-button> </template> </el-table-column> </el-table> <el-dialog title="Delete objects" :visible.sync="dialogVisible" width="30%" :before-close="handleClose"> <span>{{ deleteObject }} Objects will be deleted</span> <span slot="footer" class="dialog-footer"> <el-button @click="dialogVisible = false">Cancel</el-button> <el-button type="primary" @click="deleteOK()">Confirm</el-button> </span> </el-dialog> </div> </template></pre> <pre><script> import Vue from 'vue' import Amplify, { API,Storage } from 'aws-amplify'; import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' import locale from 'element-ui/lib/locale/lang/en' Vue.use(ElementUI, { locale }) export default { name: 'Home', data () { return { s3Data: [], dialogVisible: false, selectedRow: "", deleteObject: "", uploadObject:"" } }, created () { this.refresh() }, methods: { refresh () { Storage.list('') .then(result => this.s3Data = JSON.parse(JSON.stringify(result))) .catch(err => console.log(err)); }, // 一時停止 pause(){ console.log(`★${new Date().toLocaleString()}_転送中断`) this.uploadObject.pause() }, // 再開 resume(){ console.log(`★${new Date().toLocaleString()}_転送再開`) this.uploadObject.resume() }, // 中断 cancel(){ console.log(`★${new Date().toLocaleString()}_転送中止`) Storage.cancel(this.uploadObject); }, upload(e) { var files = e.target.files || e.dataTransfer.files console.log(`★${new Date().toLocaleString()}_転送開始`) this.uploadObject = Storage.put(files[0].name, files[0],{ resumable: true, progressCallback: (progress) => { console.log(`★${new Date().toLocaleString()}_${progress.loaded}/${progress.total}送信済...`) if(progress.loaded == progress.total){ console.log(`★${new Date().toLocaleString()}_転送終了`) } } }) }, download (row) { Storage.get(row['key'], { download: true }) .then(result => { console.log(result) const url = URL.createObjectURL(new Blob([result.Body])); const link = document.createElement('a') link.href = url link.download = row['key'] console.log(link) link.click() }) .catch(err => console.log(err)); }, openDeleteDialog(row) { this.selectedRow = row; console.log(row) this.deleteObject = row['key']; this.dialogVisible = true }, deleteOK () { this.dialogVisible = false Storage.remove(this.selectedRow['key']) .then(result => { console.log(result) this.refresh() } ) .catch(err => console.log(err)); }, handleClose(done) { this.$confirm('Are you sure to close this dialog?') .then(_ => { done(); }) .catch(_ => {}); } } } </script> <style> label { color: #606266; background-color:white; padding: 10px; } </style></pre> <pre>
画面はこんな感じになりました。
動かしてみる
Chrome の F12 でログを確認しながらそれぞれの動きを確認してみます。デバッグログがたくさん出るので、「★」でフィルターして確認してます。
一時停止、再開、キャンセル
「Upload」からアップロードを始めると、転送が始まります。監視ログでどのくらい転送が進んだかが分かります。
「pause」で中断すると、転送も中断し監視ログも止まりました。「resume」から再開をすると「120586240/1073741824」となり、途中から再開されているのがかわります。
★2021/11/8 16:56:14_転送開始 ★2021/11/8 16:56:14_5242880/1073741824送信済... ★2021/11/8 16:56:15_10485760/1073741824送信済... ★2021/11/8 16:56:15_15728640/1073741824送信済... ~略~ ★2021/11/8 16:56:16_104857600/1073741824送信済... ★2021/11/8 16:56:16_110100480/1073741824送信済... ★2021/11/8 16:56:17_115343360/1073741824送信済... ★2021/11/8 16:56:17_転送中断 ★2021/11/8 16:56:20_転送再開 ★2021/11/8 16:56:20_120586240/1073741824送信済... ★2021/11/8 16:56:20_125829120/1073741824送信済... ★2021/11/8 16:56:20_131072000/1073741824送信済... ~略~ ★2021/11/8 16:56:22_214958080/1073741824送信済... ★2021/11/8 16:56:22_220200960/1073741824送信済... ★2021/11/8 16:56:22_225443840/1073741824送信済... ★2021/11/8 16:56:22_転送中止
強制終了からの再アップロード
ある程度送信した後、画面をリフレッシュして、通信を強制切断してみます。その後、「Upload」から再度アップロードボタンからアップロードをしてみます。
最初から「466616320/1073741824」なので、最初に送信した分は無駄にならず、途中から再開されているのが分かります。
★2021/11/8 17:06:50_転送開始 ★2021/11/8 17:06:50_466616320/1073741824送信済... ★2021/11/8 17:06:51_471859200/1073741824送信済... ★2021/11/8 17:06:51_477102080/1073741824送信済... ★2021/11/8 17:06:51_482344960/1073741824送信済... ★2021/11/8 17:06:51_487587840/1073741824送信済...
最後に
amplify 初めて触ったのですが、あっという間にリソースが作成されて感動しました。普段触らない機能を触ると楽しいですね。どなたかのお役に立てれば幸いです。
参考
[1]ストレージ-ファイルのアップロード-JavaScript-AWSAmplify Docs
[2]AWS Amplify for JavaScript がストレージのリジューム可能なファイルアップロードをサポート